#ifndef _BSP_ATK_NAND_H
#define _BSP_ATK_NAND_H
#include "common.h"
//////////////////////////////////////////////////////////////////////////////////	 
//本程序只供学习使用，未经作者许可，不得用于其它任何用途
//ALIENTEK STM32开发板
//NAND FLASH 驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/15
//版本：V1.5
//版权所有，盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved					  
//********************************************************************************
//升级说明
//V1.1 20160520
//1,新增硬件ECC支持(仅在以NAND_ECC_SECTOR_SIZE大小为单位进行读写时处理)
//2,新增NAND_Delay函数,用于等待tADL/tWHR
//3,新增NAND_WritePageConst函数,用于搜寻坏块.
//V1.2 20160525
//1,去掉NAND_SEC_SIZE宏定义，由NAND_ECC_SECTOR_SIZE替代
//2,去掉nand_dev结构体里面的secbuf指针，用不到
//V1.3 20160907
//1,定义NAND_TADL_DELAY宏,用于设置tADL的延迟时间,方便修改
//V1.4 20180321
//1,新增对H27U4G8F2E芯片的支持
//2,修改MEMSET/MEMHOLD/MEMHIZ等延时,以支持H27U4G08F2E.
//V1.5 20180531
//1.增加NAND_TWHR_DELAY/NAND_TRHW_DELAY/NAND_TPROG_DELAY/NAND_TBERS_DELAY四个延时,防止出错
//2.擦除时增加ms级别的延时，防止擦除时间不够立马进行读状态而造成出错 
////////////////////////////////////////////////////////////////////////////////// 	


#define NAND_MAX_PAGE_SIZE			4096		//定义NAND FLASH的最大的PAGE大小（不包括SPARE区），默认4096字节
#define NAND_ECC_SECTOR_SIZE		512			//执行ECC计算的单元大小，默认512字节


//NAND FLASH操作相关延时函数
#define NAND_TADL_DELAY				30			//tADL等待延迟,最少70ns
#define NAND_TWHR_DELAY				25			//tWHR等待延迟,最少60ns
#define NAND_TRHW_DELAY				35			//tRHW等待延迟,最少100ns
#define NAND_TPROG_DELAY			200			//tPROG等待延迟,典型值200us,最大需要700us
#define NAND_TBERS_DELAY			4			//tBERS等待延迟,典型值3.5ms,最大需要10ms


//NAND属性结构体
typedef struct
{
    u16 page_totalsize;     	//每页总大小，main区和spare区总和
    u16 page_mainsize;      	//每页的main区大小
    u16 page_sparesize;     	//每页的spare区大小
    u8  block_pagenum;      	//每个块包含的页数量
    u16 plane_blocknum;     	//每个plane包含的块数量
    u16 block_totalnum;     	//总的块数量
    u16 good_blocknum;      	//好块数量    
    u16 valid_blocknum;     	//有效块数量(供文件系统使用的好块数量)
	u8 ecc_err_st;				//ECC 错误状态，无法修复的个数，执行page_read后获取
	u8 ecc_cok_st;				//ECC 修改状态，修复成功的个数，执行page_read后获取
    u32 id;             		//NAND FLASH ID
	u32 ecc_hard;				//硬件计算出来的ECC值
	u32 ecc_hdbuf[NAND_MAX_PAGE_SIZE/NAND_ECC_SECTOR_SIZE];//ECC硬件计算值缓冲区  	
	u32 ecc_rdbuf[NAND_MAX_PAGE_SIZE/NAND_ECC_SECTOR_SIZE];//ECC读取的值缓冲区
}nand_attriute;      

extern nand_attriute atk_nand;				//nand重要参数结构体 

#define NAND_RB  				 PDin(6)	//NAND Flash的闲/忙引脚 


#define NAND_ADDRESS			0x70000000U	//nand flash的访问地址,接NCE2,地址为:0X8000 0000
//#define NAND_ADDRESS			0X80000000U	//nand flash的访问地址,接NCE3,地址为:0X8000 0000
#define NAND_CMD				1<<16		//发送命令
#define NAND_ADDR				1<<17		//发送地址

//NAND FLASH命令
#define NAND_READID         	0X90    	//读ID指令
#define NAND_FEATURE			0XEF    	//设置特性指令
#define NAND_RESET          	0XFF    	//复位NAND
#define NAND_READSTA        	0X70   	 	//读状态
#define NAND_AREA_A         	0X00   
#define NAND_AREA_TRUE1     	0X30  
#define NAND_WRITE0        	 	0X80
#define NAND_WRITE_TURE1    	0X10
#define NAND_ERASE0        	 	0X60
#define NAND_ERASE1         	0XD0
#define NAND_MOVEDATA_CMD0  	0X00
#define NAND_MOVEDATA_CMD1  	0X35
#define NAND_MOVEDATA_CMD2  	0X85
#define NAND_MOVEDATA_CMD3  	0X10

//NAND FLASH状态
#define NSTA_READY       	   	0X40		//nand已经准备好
#define NSTA_ERROR				0X01		//nand错误
#define NSTA_TIMEOUT        	0X02		//超时
#define NSTA_ECC1BITERR       	0X03		//ECC 1bit错误
#define NSTA_ECC2BITERR       	0X04		//ECC 2bit以上错误


//NAND FLASH型号和对应的ID号
#define MT29F1G08ABADA			0XF1809502	//MT29F1G08ABADA
#define MT29F4G08ABADA			0XDC909556	//MT29F4G08ABADA
#define MT29F16G08ABABA			0X48002689	//MT29F16G08ABABA

u8 atk_nand_init(void);
u8 atk_nand_mode_set(u8 mode);
u32 atk_nand_read_id(void);
u8 atk_nand_read_status(void);
u8 atk_nand_wait_ready(void);
u8 atk_nand_reset(void);
u8 atk_nand_wait_rb(vu8 rb);
void atk_nand_delay(vu32 i);
u8 atk_nand_read_page(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead);
u8 atk_nand_read_page_comp(u32 PageNum,u16 ColNum,u32 CmpVal,u16 NumByteToRead,u16 *NumByteEqual);
u8 atk_nand_write_page(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToWrite);
u8 atk_nand_write_page_const(u32 PageNum,u16 ColNum,u32 cval,u16 NumByteToWrite);
u8 atk_nand_copy_page_without_write(u32 Source_PageNum,u32 Dest_PageNum);
u8 atk_nand_copy_page_with_write(u32 Source_PageNum,u32 Dest_PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToWrite);
u8 atk_nand_read_spare(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead);
u8 atk_nand_write_spare(u32 PageNum,u16 ColNum,u8 *pBuffer,u16 NumByteToRead);
u8 atk_nand_erase_block(u32 BlockNum);
void atk_nand_erase_chip(void);

// 整页 页读 页写， main+spare数据16字节
u8 atk_nand_read_cpage(u32 PageNum, u8 *pBuffer);
u8 atk_nand_write_cpage(u32 PageNum, u8 *pBuffer);

u16 atk_nand_get_OE(u8 oe,u32 eccval);
u8 atk_nand_ecc_correct(u8* data_buf,u32 eccrd,u32 ecccl);
#endif



















